﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.View.Tableaus.CharacterTableau
// Assembly: TaleWorlds.MountAndBlade.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 61152EB8-513B-4D4A-8AC0-0D1465C6CF6C
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\Modules\Native\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.View.dll

using System;
using TaleWorlds.Core;
using TaleWorlds.Core.ViewModelCollection;
using TaleWorlds.DotNet;
using TaleWorlds.Engine;
using TaleWorlds.Engine.Options;
using TaleWorlds.InputSystem;
using TaleWorlds.Library;

#nullable disable
namespace TaleWorlds.MountAndBlade.View.Tableaus
{
  public class CharacterTableau
  {
    private bool _isFinalized;
    private MatrixFrame _mountSpawnPoint;
    private MatrixFrame _bannerSpawnPoint;
    private float _animationFrequencyThreshold = 2.5f;
    private MatrixFrame _initialSpawnFrame;
    private MatrixFrame _characterMountPositionFrame;
    private MatrixFrame _mountCharacterPositionFrame;
    private AgentVisuals _agentVisuals;
    private AgentVisuals _mountVisuals;
    private int _agentVisualLoadingCounter;
    private int _mountVisualLoadingCounter;
    private AgentVisuals _oldAgentVisuals;
    private AgentVisuals _oldMountVisuals;
    private int _initialLoadingCounter;
    private ActionIndexCache _idleAction;
    private string _idleFaceAnim;
    private Scene _tableauScene;
    private MBAgentRendererSceneController _agentRendererSceneController;
    private Camera _continuousRenderCamera;
    private float _cameraRatio;
    private MatrixFrame _camPos;
    private MatrixFrame _camPosGatheredFromScene;
    private string _charStringId;
    private int _tableauSizeX;
    private int _tableauSizeY;
    private uint _clothColor1 = new Color(1f, 1f, 1f).ToUnsignedInteger();
    private uint _clothColor2 = new Color(1f, 1f, 1f).ToUnsignedInteger();
    private bool _isRotatingCharacter;
    private bool _isCharacterMountPlacesSwapped;
    private string _mountCreationKey = "";
    private string _equipmentCode = "";
    private bool _isEquipmentAnimActive;
    private float _animationGap;
    private float _mainCharacterRotation;
    private bool _isEnabled;
    private float RenderScale = 1f;
    private float _customRenderScale = 1f;
    private int _latestWidth = -1;
    private int _latestHeight = -1;
    private string _bodyPropertiesCode;
    private BodyProperties _bodyProperties = BodyProperties.Default;
    private bool _isFemale;
    private CharacterViewModel.StanceTypes _stanceIndex;
    private Equipment _equipment;
    private Banner _banner;
    private int _race;
    private bool _isBannerShownInBackground;
    private ItemObject _bannerItem;
    private GameEntity _bannerEntity;
    private static readonly ActionIndexCache act_cheer_1 = ActionIndexCache.Create("act_arena_winner_1");
    private static readonly ActionIndexCache act_inventory_idle_start = ActionIndexCache.Create(nameof (act_inventory_idle_start));
    private static readonly ActionIndexCache act_inventory_glove_equip = ActionIndexCache.Create(nameof (act_inventory_glove_equip));
    private static readonly ActionIndexCache act_inventory_cloth_equip = ActionIndexCache.Create(nameof (act_inventory_cloth_equip));
    private static readonly ActionIndexCache act_horse_stand = ActionIndexCache.Create(nameof (act_inventory_idle_start));
    private static readonly ActionIndexCache act_camel_stand = ActionIndexCache.Create(nameof (act_inventory_idle_start));
    private int _leftHandEquipmentIndex;
    private int _rightHandEquipmentIndex;
    private bool _isEquipmentIndicesDirty;
    private bool _customAnimationStartScheduled;
    private float _customAnimationTimer;
    private string _customAnimationName;
    private ActionIndexCache _customAnimation;
    private MBActionSet _characterActionSet;
    private bool _isVisualsDirty;
    private Equipment _oldEquipment;

    public Texture Texture { get; private set; }

    public bool IsRunningCustomAnimation
    {
      get
      {
        return this._customAnimation != (ActionIndexCache) null || this._customAnimationStartScheduled;
      }
    }

    public bool ShouldLoopCustomAnimation { get; set; }

    public float CustomAnimationWaitDuration { get; set; }

    private TableauView View
    {
      get
      {
        return (NativeObject) this.Texture != (NativeObject) null ? this.Texture.TableauView : (TableauView) null;
      }
    }

    public CharacterTableau()
    {
      this._leftHandEquipmentIndex = -1;
      this._rightHandEquipmentIndex = -1;
      this._isVisualsDirty = false;
      this._equipment = new Equipment();
      this.SetEnabled(true);
      this.FirstTimeInit();
    }

    public void OnTick(float dt)
    {
      if (this._customAnimationStartScheduled)
        this.StartCustomAnimation();
      if (this._customAnimation != (ActionIndexCache) null && this._characterActionSet.IsValid)
      {
        this._customAnimationTimer += dt;
        float animationDuration = MBActionSet.GetActionAnimationDuration(this._characterActionSet, this._customAnimation);
        if ((double) this._customAnimationTimer > (double) animationDuration)
        {
          if ((double) this._customAnimationTimer > (double) animationDuration + (double) this.CustomAnimationWaitDuration)
          {
            if (this.ShouldLoopCustomAnimation)
              this.StartCustomAnimation();
            else
              this.StopCustomAnimationIfCantContinue();
          }
          else
            this._agentVisuals?.SetAction(this.GetIdleAction(), 0.0f, true);
        }
      }
      if (this._isEnabled && this._isRotatingCharacter)
        this.UpdateCharacterRotation((int) Input.MouseMoveX);
      if ((double) this._animationFrequencyThreshold > (double) this._animationGap)
        this._animationGap += dt;
      if (this._isEnabled)
      {
        this._agentVisuals?.TickVisuals();
        this._oldAgentVisuals?.TickVisuals();
        this._mountVisuals?.TickVisuals();
        this._oldMountVisuals?.TickVisuals();
      }
      if ((NativeObject) this.View != (NativeObject) null)
      {
        if ((NativeObject) this._continuousRenderCamera == (NativeObject) null)
          this._continuousRenderCamera = Camera.CreateCamera();
        this.View.SetDoNotRenderThisFrame(false);
      }
      if (this._isVisualsDirty)
      {
        this.RefreshCharacterTableau(this._oldEquipment);
        this._oldEquipment = (Equipment) null;
        this._isVisualsDirty = false;
      }
      if (this._agentVisualLoadingCounter > 0 && this._agentVisuals.GetEntity().CheckResources(true, true))
        --this._agentVisualLoadingCounter;
      if (this._mountVisualLoadingCounter > 0 && this._mountVisuals.GetEntity().CheckResources(true, true))
        --this._mountVisualLoadingCounter;
      if (this._mountVisualLoadingCounter == 0 && this._agentVisualLoadingCounter == 0)
      {
        this._oldMountVisuals?.SetVisible(false);
        this._mountVisuals?.SetVisible(this._bodyProperties != BodyProperties.Default);
        this._oldAgentVisuals?.SetVisible(false);
        this._agentVisuals?.SetVisible(this._bodyProperties != BodyProperties.Default);
      }
      if (!this._isEquipmentIndicesDirty)
        return;
      this._agentVisuals.GetVisuals().SetWieldedWeaponIndices(this._rightHandEquipmentIndex, this._leftHandEquipmentIndex);
      this._isEquipmentIndicesDirty = false;
    }

    public float GetCustomAnimationProgressRatio()
    {
      if (!(this._customAnimation != (ActionIndexCache) null) || !this._characterActionSet.IsValid)
        return -1f;
      float animationDuration = MBActionSet.GetActionAnimationDuration(this._characterActionSet, this._customAnimation);
      return (double) animationDuration == 0.0 ? -1f : this._customAnimationTimer / animationDuration;
    }

    private void StopCustomAnimationIfCantContinue()
    {
      bool flag = false;
      if (this._agentVisuals != null && this._customAnimation != (ActionIndexCache) null && this._customAnimation.Index >= 0)
      {
        ActionIndexValueCache continueToAction = MBActionSet.GetActionAnimationContinueToAction(this._characterActionSet, ActionIndexValueCache.Create(this._customAnimation));
        if (continueToAction.Index >= 0)
        {
          this._customAnimationName = continueToAction.Name;
          this.StartCustomAnimation();
          flag = true;
        }
      }
      if (flag)
        return;
      this.StopCustomAnimation();
      this._customAnimationTimer = -1f;
    }

    private void SetEnabled(bool enabled)
    {
      this._isEnabled = enabled;
      this.View?.SetEnable(this._isEnabled);
    }

    public void SetLeftHandWieldedEquipmentIndex(int index)
    {
      this._leftHandEquipmentIndex = index;
      this._isEquipmentIndicesDirty = true;
    }

    public void SetRightHandWieldedEquipmentIndex(int index)
    {
      this._rightHandEquipmentIndex = index;
      this._isEquipmentIndicesDirty = true;
    }

    public void SetTargetSize(int width, int height)
    {
      this._isRotatingCharacter = false;
      this._latestWidth = width;
      this._latestHeight = height;
      if (width <= 0 || height <= 0)
      {
        this._tableauSizeX = 10;
        this._tableauSizeY = 10;
      }
      else
      {
        this.RenderScale = NativeOptions.GetConfig(NativeOptions.NativeOptionsType.ResolutionScale) / 100f;
        this._tableauSizeX = (int) ((double) width * (double) this._customRenderScale * (double) this.RenderScale);
        this._tableauSizeY = (int) ((double) height * (double) this._customRenderScale * (double) this.RenderScale);
      }
      this._cameraRatio = (float) this._tableauSizeX / (float) this._tableauSizeY;
      this.View?.SetEnable(false);
      this.View?.AddClearTask(true);
      this.Texture?.ReleaseNextFrame();
      this.Texture = TableauView.AddTableau(nameof (CharacterTableau), new RenderTargetComponent.TextureUpdateEventHandler(this.CharacterTableauContinuousRenderFunction), (object) this._tableauScene, this._tableauSizeX, this._tableauSizeY);
      this.Texture.TableauView.SetSceneUsesContour(false);
      this.Texture.TableauView.SetFocusedShadowmap(true, ref this._initialSpawnFrame.origin, 2.55f);
    }

    public void SetCharStringID(string charStringId)
    {
      if (!(this._charStringId != charStringId))
        return;
      this._charStringId = charStringId;
    }

    public void OnFinalize()
    {
      if ((NativeObject) this._continuousRenderCamera != (NativeObject) null)
      {
        lock (this._continuousRenderCamera)
        {
          this._continuousRenderCamera.ReleaseCameraEntity();
          this._continuousRenderCamera = (Camera) null;
        }
      }
      this._agentVisuals?.ResetNextFrame();
      this._agentVisuals = (AgentVisuals) null;
      this._mountVisuals?.ResetNextFrame();
      this._mountVisuals = (AgentVisuals) null;
      this._oldAgentVisuals?.ResetNextFrame();
      this._oldAgentVisuals = (AgentVisuals) null;
      this._oldMountVisuals?.ResetNextFrame();
      this._oldMountVisuals = (AgentVisuals) null;
      TableauView view = this.View;
      view?.SetEnable(false);
      if ((NativeObject) this._tableauScene != (NativeObject) null)
      {
        if ((NativeObject) this._bannerEntity != (NativeObject) null)
        {
          this._tableauScene.RemoveEntity(this._bannerEntity, 0);
          this._bannerEntity = (GameEntity) null;
        }
        if (this._agentRendererSceneController != null)
        {
          view?.SetEnable(false);
          view?.AddClearTask();
          MBAgentRendererSceneController.DestructAgentRendererSceneController(this._tableauScene, this._agentRendererSceneController, false);
          this._agentRendererSceneController = (MBAgentRendererSceneController) null;
          this._tableauScene.ManualInvalidate();
          this._tableauScene = (Scene) null;
        }
        else
        {
          TableauCacheManager.Current.ReturnCachedInventoryTableauScene();
          TableauCacheManager.Current.ReturnCachedInventoryTableauScene();
          view?.AddClearTask(true);
          this._tableauScene = (Scene) null;
        }
      }
      this.Texture?.ReleaseNextFrame();
      this.Texture = (Texture) null;
      this._isFinalized = true;
    }

    public void SetBodyProperties(string bodyPropertiesCode)
    {
      if (!(this._bodyPropertiesCode != bodyPropertiesCode))
        return;
      this._bodyPropertiesCode = bodyPropertiesCode;
      BodyProperties bodyProperties;
      this._bodyProperties = string.IsNullOrEmpty(bodyPropertiesCode) || !BodyProperties.FromString(bodyPropertiesCode, out bodyProperties) ? BodyProperties.Default : bodyProperties;
      this._isVisualsDirty = true;
    }

    public void SetStanceIndex(int index)
    {
      this._stanceIndex = (CharacterViewModel.StanceTypes) index;
      this._isVisualsDirty = true;
    }

    public void SetCustomRenderScale(float value)
    {
      if (this._customRenderScale.ApproximatelyEqualsTo(value))
        return;
      this._customRenderScale = value;
      if (this._latestWidth == -1 || this._latestHeight == -1)
        return;
      this.SetTargetSize(this._latestWidth, this._latestHeight);
    }

    private void AdjustCharacterForStanceIndex()
    {
      switch ((int) this._stanceIndex)
      {
        case 0:
          this._agentVisuals?.SetAction(this.GetIdleAction(), 0.0f, true);
          AgentVisuals oldAgentVisuals1 = this._oldAgentVisuals;
          if (oldAgentVisuals1 != null)
          {
            // ISSUE: explicit non-virtual call
            __nonvirtual (oldAgentVisuals1.SetAction(this.GetIdleAction(), 0.0f, true));
            break;
          }
          break;
        case 1:
          this._camPos = this._camPosGatheredFromScene;
          this._camPos.Elevate(-2f);
          this._camPos.Advance(0.5f);
          this._agentVisuals?.SetAction(this.GetIdleAction(), 0.0f, true);
          AgentVisuals oldAgentVisuals2 = this._oldAgentVisuals;
          if (oldAgentVisuals2 != null)
          {
            // ISSUE: explicit non-virtual call
            __nonvirtual (oldAgentVisuals2.SetAction(this.GetIdleAction(), 0.0f, true));
            break;
          }
          break;
        case 2:
        case 4:
          if (this._agentVisuals != null)
          {
            this._camPos = this._camPosGatheredFromScene;
            if (this._equipment[10].Item != null)
            {
              this._camPos.Advance(0.5f);
              this._agentVisuals.SetAction(this._mountVisuals.GetEntity().Skeleton.GetActionAtChannel(0), this._mountVisuals.GetEntity().Skeleton.GetAnimationParameterAtChannel(0), true);
              this._oldAgentVisuals.SetAction(this._mountVisuals.GetEntity().Skeleton.GetActionAtChannel(0), this._mountVisuals.GetEntity().Skeleton.GetAnimationParameterAtChannel(0), true);
              break;
            }
            this._camPos.Elevate(-2f);
            this._camPos.Advance(0.5f);
            this._agentVisuals.SetAction(this.GetIdleAction(), 0.0f, true);
            this._oldAgentVisuals.SetAction(this.GetIdleAction(), 0.0f, true);
            break;
          }
          break;
        case 3:
          this._agentVisuals?.SetAction(CharacterTableau.act_cheer_1, 0.0f, true);
          AgentVisuals oldAgentVisuals3 = this._oldAgentVisuals;
          if (oldAgentVisuals3 != null)
          {
            // ISSUE: explicit non-virtual call
            __nonvirtual (oldAgentVisuals3.SetAction(CharacterTableau.act_cheer_1, 0.0f, true));
            break;
          }
          break;
      }
      if (this._agentVisuals != null)
      {
        GameEntity entity = this._agentVisuals.GetEntity();
        Skeleton skeleton = entity.Skeleton;
        skeleton.TickAnimations(0.01f, this._agentVisuals.GetVisuals().GetGlobalFrame(), true);
        if (!string.IsNullOrEmpty(this._idleFaceAnim))
          skeleton.SetFacialAnimation(Agent.FacialAnimChannel.Mid, this._idleFaceAnim, false, true);
        entity.ManualInvalidate();
        skeleton.ManualInvalidate();
      }
      if (this._oldAgentVisuals != null)
      {
        GameEntity entity = this._oldAgentVisuals.GetEntity();
        Skeleton skeleton = entity.Skeleton;
        skeleton.TickAnimations(0.01f, this._oldAgentVisuals.GetVisuals().GetGlobalFrame(), true);
        if (!string.IsNullOrEmpty(this._idleFaceAnim))
          skeleton.SetFacialAnimation(Agent.FacialAnimChannel.Mid, this._idleFaceAnim, false, true);
        entity.ManualInvalidate();
        skeleton.ManualInvalidate();
      }
      if (this._mountVisuals != null)
      {
        GameEntity entity = this._mountVisuals.GetEntity();
        Skeleton skeleton = entity.Skeleton;
        skeleton.TickAnimations(0.01f, this._mountVisuals.GetVisuals().GetGlobalFrame(), true);
        if (!string.IsNullOrEmpty(this._idleFaceAnim))
          skeleton.SetFacialAnimation(Agent.FacialAnimChannel.Mid, this._idleFaceAnim, false, true);
        entity.ManualInvalidate();
        skeleton.ManualInvalidate();
      }
      if (this._oldMountVisuals == null)
        return;
      GameEntity entity1 = this._oldMountVisuals.GetEntity();
      Skeleton skeleton1 = entity1.Skeleton;
      skeleton1.TickAnimations(0.01f, this._oldMountVisuals.GetVisuals().GetGlobalFrame(), true);
      entity1.ManualInvalidate();
      skeleton1.ManualInvalidate();
    }

    private void ForceRefresh()
    {
      int stanceIndex = (int) this._stanceIndex;
      this._stanceIndex = (CharacterViewModel.StanceTypes) 0;
      this.SetStanceIndex(stanceIndex);
    }

    public void SetIsFemale(bool isFemale)
    {
      this._isFemale = isFemale;
      this._isVisualsDirty = true;
    }

    public void SetIsBannerShownInBackground(bool isBannerShownInBackground)
    {
      this._isBannerShownInBackground = isBannerShownInBackground;
      this._isVisualsDirty = true;
    }

    public void SetRace(int race)
    {
      this._race = race;
      this._isVisualsDirty = true;
    }

    public void SetIdleAction(string idleAction)
    {
      this._idleAction = ActionIndexCache.Create(idleAction);
      this._isVisualsDirty = true;
    }

    public void SetCustomAnimation(string animation) => this._customAnimationName = animation;

    public void StartCustomAnimation()
    {
      if (this._isVisualsDirty || this._agentVisuals == null || string.IsNullOrEmpty(this._customAnimationName))
      {
        this._customAnimationStartScheduled = true;
      }
      else
      {
        this.StopCustomAnimation();
        this._customAnimation = ActionIndexCache.Create(this._customAnimationName);
        if (this._customAnimation.Index >= 0)
        {
          this._agentVisuals.SetAction(this._customAnimation, 0.0f, true);
          this._customAnimationStartScheduled = false;
          this._customAnimationTimer = 0.0f;
        }
        else
          Debug.FailedAssert("Invalid custom animation in character tableau: " + this._customAnimationName, "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.MountAndBlade.View\\Tableaus\\CharacterTableau.cs", nameof (StartCustomAnimation), 602);
      }
    }

    public void StopCustomAnimation()
    {
      if (this._agentVisuals == null || !(this._customAnimation != (ActionIndexCache) null))
        return;
      if (MBActionSet.GetActionAnimationContinueToAction(this._characterActionSet, ActionIndexValueCache.Create(this._customAnimation)).Index < 0)
        this._agentVisuals.SetAction(this.GetIdleAction(), 0.0f, true);
      this._customAnimation = (ActionIndexCache) null;
    }

    public void SetIdleFaceAnim(string idleFaceAnim)
    {
      if (string.IsNullOrEmpty(idleFaceAnim))
        return;
      this._idleFaceAnim = idleFaceAnim;
      this._isVisualsDirty = true;
    }

    public void SetEquipmentCode(string equipmentCode)
    {
      if (!(this._equipmentCode != equipmentCode) || string.IsNullOrEmpty(equipmentCode))
        return;
      this._oldEquipment = Equipment.CreateFromEquipmentCode(this._equipmentCode);
      this._equipmentCode = equipmentCode;
      this._equipment = Equipment.CreateFromEquipmentCode(equipmentCode);
      this._bannerItem = this.GetAndRemoveBannerFromEquipment(ref this._equipment);
      this._isVisualsDirty = true;
    }

    public void SetIsEquipmentAnimActive(bool value) => this._isEquipmentAnimActive = value;

    public void SetMountCreationKey(string value)
    {
      if (!(this._mountCreationKey != value))
        return;
      this._mountCreationKey = value;
      this._isVisualsDirty = true;
    }

    public void SetBannerCode(string value)
    {
      this._banner = !string.IsNullOrEmpty(value) ? BannerCode.CreateFrom(value).CalculateBanner() : (Banner) null;
      this._isVisualsDirty = true;
    }

    public void SetArmorColor1(uint clothColor1)
    {
      if ((int) this._clothColor1 == (int) clothColor1)
        return;
      this._clothColor1 = clothColor1;
      this._isVisualsDirty = true;
    }

    public void SetArmorColor2(uint clothColor2)
    {
      if ((int) this._clothColor2 == (int) clothColor2)
        return;
      this._clothColor2 = clothColor2;
      this._isVisualsDirty = true;
    }

    private ActionIndexCache GetIdleAction()
    {
      ActionIndexCache idleAction = this._idleAction;
      return (object) idleAction != null ? idleAction : CharacterTableau.act_inventory_idle_start;
    }

    private void RefreshCharacterTableau(Equipment oldEquipment = null)
    {
      this.UpdateMount(this._stanceIndex == 4);
      this.UpdateBannerItem();
      if (this._mountVisuals == null && this._isCharacterMountPlacesSwapped)
      {
        this._isCharacterMountPlacesSwapped = false;
        this._mainCharacterRotation = 0.0f;
      }
      if (this._agentVisuals != null)
      {
        bool visibilityExcludeParents = this._oldAgentVisuals.GetEntity().GetVisibilityExcludeParents();
        AgentVisuals agentVisuals = this._agentVisuals;
        this._agentVisuals = this._oldAgentVisuals;
        this._oldAgentVisuals = agentVisuals;
        this._agentVisualLoadingCounter = 1;
        AgentVisualsData agentVisualsData = this._agentVisuals.GetCopyAgentVisualsData();
        MatrixFrame frame = this._isCharacterMountPlacesSwapped ? this._characterMountPositionFrame : this._initialSpawnFrame;
        if (!this._isCharacterMountPlacesSwapped)
          frame.rotation.RotateAboutUp(this._mainCharacterRotation);
        this._characterActionSet = MBGlobals.GetActionSetWithSuffix(agentVisualsData.MonsterData, this._isFemale, "_warrior");
        agentVisualsData.BodyProperties(this._bodyProperties).SkeletonType(this._isFemale ? SkeletonType.Female : SkeletonType.Male).Frame(frame).ActionSet(this._characterActionSet).Equipment(this._equipment).Banner(this._banner).UseMorphAnims(true).ClothColor1(this._clothColor1).ClothColor2(this._clothColor2).Race(this._race);
        if (this._initialLoadingCounter > 0)
          --this._initialLoadingCounter;
        this._agentVisuals.Refresh(false, agentVisualsData, false);
        this._agentVisuals.SetVisible(false);
        if (this._initialLoadingCounter == 0)
          this._oldAgentVisuals.SetVisible(visibilityExcludeParents);
        if (oldEquipment != null && (double) this._animationFrequencyThreshold <= (double) this._animationGap && this._isEquipmentAnimActive)
        {
          EquipmentElement equipmentElement = this._equipment[EquipmentIndex.Gloves];
          if (equipmentElement.Item != null)
          {
            equipmentElement = oldEquipment[EquipmentIndex.Gloves];
            ItemObject itemObject1 = equipmentElement.Item;
            equipmentElement = this._equipment[EquipmentIndex.Gloves];
            ItemObject itemObject2 = equipmentElement.Item;
            if (itemObject1 != itemObject2)
            {
              this._agentVisuals.GetVisuals().GetSkeleton().SetAgentActionChannel(0, CharacterTableau.act_inventory_glove_equip);
              this._animationGap = 0.0f;
              goto label_16;
            }
          }
          equipmentElement = this._equipment[EquipmentIndex.Body];
          if (equipmentElement.Item != null)
          {
            equipmentElement = oldEquipment[EquipmentIndex.Body];
            ItemObject itemObject3 = equipmentElement.Item;
            equipmentElement = this._equipment[EquipmentIndex.Body];
            ItemObject itemObject4 = equipmentElement.Item;
            if (itemObject3 != itemObject4)
            {
              this._agentVisuals.GetVisuals().GetSkeleton().SetAgentActionChannel(0, CharacterTableau.act_inventory_cloth_equip);
              this._animationGap = 0.0f;
            }
          }
        }
label_16:
        this._agentVisuals.GetEntity().CheckResources(true, true);
      }
      this.AdjustCharacterForStanceIndex();
    }

    public void RotateCharacter(bool value) => this._isRotatingCharacter = value;

    public void TriggerCharacterMountPlacesSwap()
    {
      this._mainCharacterRotation = 0.0f;
      this._isCharacterMountPlacesSwapped = !this._isCharacterMountPlacesSwapped;
      this._isVisualsDirty = true;
    }

    public void OnCharacterTableauMouseMove(int mouseMoveX)
    {
      this.UpdateCharacterRotation(mouseMoveX);
    }

    private void UpdateCharacterRotation(int mouseMoveX)
    {
      if (this._agentVisuals == null)
        return;
      float a = (float) mouseMoveX * 0.005f;
      this._mainCharacterRotation += a;
      if (this._isCharacterMountPlacesSwapped)
      {
        MatrixFrame frame = this._mountVisuals.GetEntity().GetFrame();
        frame.rotation.RotateAboutUp(a);
        this._mountVisuals.GetEntity().SetFrame(ref frame);
      }
      else
      {
        MatrixFrame frame = this._agentVisuals.GetEntity().GetFrame();
        frame.rotation.RotateAboutUp(a);
        this._agentVisuals.GetEntity().SetFrame(ref frame);
      }
    }

    private void FirstTimeInit()
    {
      if (this._equipment == null)
        return;
      if ((NativeObject) this._tableauScene == (NativeObject) null)
      {
        if (TableauCacheManager.Current.IsCachedInventoryTableauSceneUsed())
        {
          this._tableauScene = Scene.CreateNewScene(enable_decals: false);
          this._tableauScene.SetName(nameof (CharacterTableau));
          this._tableauScene.DisableStaticShadows(true);
          this._tableauScene.SetClothSimulationState(true);
          this._agentRendererSceneController = MBAgentRendererSceneController.CreateNewAgentRendererSceneController(this._tableauScene, 32);
          this._tableauScene.Read("inventory_character_scene", ref new SceneInitializationData(true)
          {
            InitPhysicsWorld = false,
            DoNotUseLoadingScreen = true
          });
        }
        else
          this._tableauScene = TableauCacheManager.Current.GetCachedInventoryTableauScene();
        this._tableauScene.SetShadow(true);
        this._tableauScene.SetClothSimulationState(true);
        this._camPos = this._camPosGatheredFromScene = TableauCacheManager.Current.InventorySceneCameraFrame;
        this._mountSpawnPoint = this._tableauScene.FindEntityWithTag("horse_inv").GetGlobalFrame();
        this._bannerSpawnPoint = this._tableauScene.FindEntityWithTag("banner_inv").GetGlobalFrame();
        this._initialSpawnFrame = this._tableauScene.FindEntityWithTag("agent_inv").GetGlobalFrame();
        this._characterMountPositionFrame = new MatrixFrame(this._initialSpawnFrame.rotation, this._mountSpawnPoint.origin);
        this._characterMountPositionFrame.Strafe(-0.25f);
        this._mountCharacterPositionFrame = new MatrixFrame(this._mountSpawnPoint.rotation, this._initialSpawnFrame.origin);
        this._mountCharacterPositionFrame.Strafe(0.25f);
        if (this._agentRendererSceneController != null)
        {
          this._tableauScene.RemoveEntity(this._tableauScene.FindEntityWithTag("agent_inv"), 99);
          this._tableauScene.RemoveEntity(this._tableauScene.FindEntityWithTag("horse_inv"), 100);
          this._tableauScene.RemoveEntity(this._tableauScene.FindEntityWithTag("banner_inv"), 101);
        }
      }
      this.InitializeAgentVisuals();
      this._isVisualsDirty = true;
    }

    private void InitializeAgentVisuals()
    {
      Monster baseMonsterFromRace = TaleWorlds.Core.FaceGen.GetBaseMonsterFromRace(this._race);
      this._characterActionSet = MBGlobals.GetActionSetWithSuffix(baseMonsterFromRace, this._isFemale, "_warrior");
      this._oldAgentVisuals = AgentVisuals.Create(new AgentVisualsData().Banner(this._banner).Equipment(this._equipment).BodyProperties(this._bodyProperties).Race(this._race).Frame(this._initialSpawnFrame).UseMorphAnims(true).ActionSet(this._characterActionSet).ActionCode(this.GetIdleAction()).Scene(this._tableauScene).Monster(baseMonsterFromRace).PrepareImmediately(false).SkeletonType(this._isFemale ? SkeletonType.Female : SkeletonType.Male).ClothColor1(this._clothColor1).ClothColor2(this._clothColor2).CharacterObjectStringId(this._charStringId), nameof (CharacterTableau), false, false, false);
      this._oldAgentVisuals.SetAgentLodZeroOrMaxExternal(true);
      this._oldAgentVisuals.SetVisible(false);
      this._agentVisuals = AgentVisuals.Create(new AgentVisualsData().Banner(this._banner).Equipment(this._equipment).BodyProperties(this._bodyProperties).Race(this._race).Frame(this._initialSpawnFrame).UseMorphAnims(true).ActionSet(this._characterActionSet).ActionCode(this.GetIdleAction()).Scene(this._tableauScene).Monster(baseMonsterFromRace).PrepareImmediately(false).SkeletonType(this._isFemale ? SkeletonType.Female : SkeletonType.Male).ClothColor1(this._clothColor1).ClothColor2(this._clothColor2).CharacterObjectStringId(this._charStringId), nameof (CharacterTableau), false, false, false);
      this._agentVisuals.SetAgentLodZeroOrMaxExternal(true);
      this._agentVisuals.SetVisible(false);
      this._initialLoadingCounter = 2;
      if (string.IsNullOrEmpty(this._idleFaceAnim))
        return;
      this._agentVisuals.GetVisuals().GetSkeleton().SetFacialAnimation(Agent.FacialAnimChannel.Mid, this._idleFaceAnim, false, true);
      this._oldAgentVisuals.GetVisuals().GetSkeleton().SetFacialAnimation(Agent.FacialAnimChannel.Mid, this._idleFaceAnim, false, true);
    }

    private void UpdateMount(bool isRiderAgentMounted = false)
    {
      EquipmentElement equipmentElement = this._equipment[EquipmentIndex.ArmorItemEndSlot];
      if (equipmentElement.Item?.HorseComponent != null)
      {
        equipmentElement = this._equipment[EquipmentIndex.ArmorItemEndSlot];
        ItemObject itemObject = equipmentElement.Item;
        Monster monster = itemObject.HorseComponent.Monster;
        Equipment equipment = new Equipment()
        {
          [EquipmentIndex.ArmorItemEndSlot] = this._equipment[EquipmentIndex.ArmorItemEndSlot],
          [EquipmentIndex.HorseHarness] = this._equipment[EquipmentIndex.HorseHarness]
        };
        MatrixFrame frame = this._isCharacterMountPlacesSwapped ? this._mountCharacterPositionFrame : this._mountSpawnPoint;
        if (this._isCharacterMountPlacesSwapped)
          frame.rotation.RotateAboutUp(this._mainCharacterRotation);
        if (this._oldMountVisuals != null)
          this._oldMountVisuals.ResetNextFrame();
        this._oldMountVisuals = this._mountVisuals;
        this._mountVisualLoadingCounter = 3;
        AgentVisualsData data = new AgentVisualsData();
        data.Banner(this._banner).Equipment(equipment).Frame(frame).Scale(itemObject.ScaleFactor).ActionSet(MBGlobals.GetActionSet(monster.ActionSetCode)).ActionCode(isRiderAgentMounted ? (monster.MonsterUsage == "camel" ? CharacterTableau.act_camel_stand : CharacterTableau.act_horse_stand) : this.GetIdleAction()).Scene(this._tableauScene).Monster(monster).PrepareImmediately(false).ClothColor1(this._clothColor1).ClothColor2(this._clothColor2).MountCreationKey(this._mountCreationKey);
        this._mountVisuals = AgentVisuals.Create(data, "MountTableau", false, false, false);
        this._mountVisuals.SetAgentLodZeroOrMaxExternal(true);
        this._mountVisuals.SetVisible(false);
        this._mountVisuals.GetEntity().CheckResources(true, true);
      }
      else
      {
        if (this._mountVisuals == null)
          return;
        this._mountVisuals.Reset();
        this._mountVisuals = (AgentVisuals) null;
        this._mountVisualLoadingCounter = 0;
      }
    }

    private void UpdateBannerItem()
    {
      if ((NativeObject) this._bannerEntity != (NativeObject) null)
      {
        this._tableauScene.RemoveEntity(this._bannerEntity, 0);
        this._bannerEntity = (GameEntity) null;
      }
      if (!this._isBannerShownInBackground || this._bannerItem == null)
        return;
      this._bannerEntity = GameEntity.CreateEmpty(this._tableauScene);
      this._bannerEntity.SetFrame(ref this._bannerSpawnPoint);
      this._bannerEntity.AddMultiMesh(this._bannerItem.GetMultiMeshCopy());
      if (this._banner == null)
        return;
      this._banner.GetTableauTextureLarge((Action<Texture>) (t => this.OnBannerTableauRenderDone(t)));
    }

    private void OnBannerTableauRenderDone(Texture newTexture)
    {
      if (this._isFinalized || (NativeObject) this._bannerEntity == (NativeObject) null)
        return;
      foreach (Mesh bannerMesh in this._bannerEntity.GetAllMeshesWithTag("banner_replacement_mesh"))
        this.ApplyBannerTextureToMesh(bannerMesh, newTexture);
      if (this._bannerEntity.Skeleton?.GetAllMeshes() == null)
        return;
      foreach (Mesh allMesh in this._bannerEntity.Skeleton?.GetAllMeshes())
      {
        if (allMesh.HasTag("banner_replacement_mesh"))
          this.ApplyBannerTextureToMesh(allMesh, newTexture);
      }
    }

    private void ApplyBannerTextureToMesh(Mesh bannerMesh, Texture bannerTexture)
    {
      if (!((NativeObject) bannerMesh != (NativeObject) null))
        return;
      Material copy = bannerMesh.GetMaterial().CreateCopy();
      copy.SetTexture(Material.MBTextureType.DiffuseMap2, bannerTexture);
      uint materialShaderFlagMask = (uint) copy.GetShader().GetMaterialShaderFlagMask("use_tableau_blending");
      ulong shaderFlags = copy.GetShaderFlags();
      copy.SetShaderFlags(shaderFlags | (ulong) materialShaderFlagMask);
      bannerMesh.SetMaterial(copy);
    }

    private ItemObject GetAndRemoveBannerFromEquipment(ref Equipment equipment)
    {
      ItemObject bannerFromEquipment = (ItemObject) null;
      EquipmentElement equipmentElement = equipment[EquipmentIndex.ExtraWeaponSlot];
      ItemObject itemObject = equipmentElement.Item;
      if ((itemObject != null ? (itemObject.IsBannerItem ? 1 : 0) : 0) != 0)
      {
        equipmentElement = equipment[EquipmentIndex.ExtraWeaponSlot];
        bannerFromEquipment = equipmentElement.Item;
        equipment[EquipmentIndex.ExtraWeaponSlot] = EquipmentElement.Invalid;
      }
      return bannerFromEquipment;
    }

    internal void CharacterTableauContinuousRenderFunction(Texture sender, EventArgs e)
    {
      Scene userData = (Scene) sender.UserData;
      TableauView tableauView = sender.TableauView;
      if ((NativeObject) userData == (NativeObject) null)
      {
        tableauView.SetContinuousRendering(false);
        tableauView.SetDeleteAfterRendering(true);
      }
      else
      {
        userData.EnsurePostfxSystem();
        userData.SetDofMode(false);
        userData.SetMotionBlurMode(false);
        userData.SetBloom(true);
        userData.SetDynamicShadowmapCascadesRadiusMultiplier(0.31f);
        tableauView.SetRenderWithPostfx(true);
        float cameraRatio = this._cameraRatio;
        MatrixFrame camPos = this._camPos;
        if (!((NativeObject) this._continuousRenderCamera != (NativeObject) null))
          return;
        lock (this._continuousRenderCamera)
        {
          Camera continuousRenderCamera = this._continuousRenderCamera;
          this._continuousRenderCamera = (Camera) null;
          continuousRenderCamera.SetFovVertical(0.7853982f, cameraRatio, 0.2f, 200f);
          continuousRenderCamera.Frame = camPos;
          tableauView.SetCamera(continuousRenderCamera);
          tableauView.SetScene(userData);
          tableauView.SetSceneUsesSkybox(false);
          tableauView.SetDeleteAfterRendering(false);
          tableauView.SetContinuousRendering(true);
          tableauView.SetDoNotRenderThisFrame(true);
          tableauView.SetClearColor(0U);
          tableauView.SetFocusedShadowmap(true, ref this._initialSpawnFrame.origin, 1.55f);
        }
      }
    }
  }
}
